class Snake {

  // 定义蛇头的元素
  head: HTMLElement
  // 蛇身体 HTMLCollection 元素的集合, 会根据元素实时刷新
  bodies: HTMLCollection
  // 蛇的容器
  element: HTMLElement

  constructor() {
    this.element = document.getElementById('snake')!
    this.head = document.querySelector("#snake > div") as HTMLElement
    this.bodies = document.getElementById("snake")!.getElementsByTagName('div') // 获取到 HTMLCollection集合
  }

  // 获取蛇头坐标
  get X() {
    return this.head.offsetLeft
  }
  get Y() {
    return this.head.offsetTop
  }

  // 设置蛇头坐标
  set X(value: number) {
    if(this.X === value) return
    if(value < 0 || value > 290) throw new Error('撞墙了!!!') // 抛出异常,用 try catch捕获
    // 处理掉头问题 以下的方法虽然可以让蛇不掉头,但是在控制器里面设置的蛇的运动方向会被改变, 则蛇头的位置也会改变, 这样就会出现蛇头还没撞墙但身体已经出墙
    // if(this.bodies[1] && (this.bodies[1] as HTMLElement).offsetLeft === value) {
    //   if(value > this.X) {
    //     value = this.X - 10
    //   }else {
    //     value = this.X + 10
    //   }
    // }
    this.moveBody()
    this.head.style.left = value + 'px'
    this.checkHeadBody()
  }
  set Y(value: number) {
    if(this.Y === value) return
    if(value < 0 || value > 290) throw new Error('撞墙了!!!') // 抛出异常,用 try catch捕获
    // 处理掉头问题 以下的方法虽然可以让蛇不掉头,但是在控制器里面设置的蛇的运动方向会被改变, 则蛇头的位置也会改变, 这样就会出现蛇头还没撞墙但身体已经出墙
    // if(this.bodies[1] && (this.bodies[1] as HTMLElement).offsetTop === value) {
    //   if(value > this.Y) {
    //     value = this.Y - 10
    //   }else {
    //     value = this.Y + 10
    //   }
    // }
    this.moveBody()
    this.head.style.top = value + 'px'
    this.checkHeadBody()
  }

  // 吃到食物, 增加蛇身
  addBody() {
    this.element.insertAdjacentHTML('beforeend', "<div></div>")
  }

  // 蛇身的移动 每次增加的身体应该在上一节蛇身的位置, 所有在改变蛇身的位置时,应该在蛇身的最后一节开始改动
  moveBody() {
    for (let index = this.bodies.length - 1; index > 0; index--) {
      // 获取前一节蛇身的位置
      let X = (this.bodies[index - 1] as HTMLElement).offsetLeft;
      let Y = (this.bodies[index - 1] as HTMLElement).offsetTop;
      (this.bodies[index] as HTMLElement).style.left = X + 'px';
      (this.bodies[index] as HTMLElement).style.top = Y + 'px';
    }
  }

  // 检查头和身体有没有相撞
  checkHeadBody() {
    for (let index = 4; index < this.bodies.length; index++) {
      let bod = this.bodies[index] as HTMLElement
      if(this.X === bod.offsetLeft && this.Y === bod.offsetTop) {
        throw new Error("撞到自己了");
        
      }
      
    }
  }

}

export default Snake